package sf.r2dbc.type;

import io.r2dbc.spi.Row;
import io.r2dbc.spi.Statement;
import io.r2dbc.spi.Type;
import sf.database.dialect.DBDialect;
import sf.database.meta.ColumnMapping;

public interface R2dbcTypeHandler<T> {
    /**
     * 从结果集里获取一个字段的值
     * @param rs          结果集
     * @param columnLabel 列名
     * @return 字段值
     */
    T get(Row rs, String columnLabel);

    /**
     * 从结果集里获取一个字段的值
     * @param rs          结果集
     * @param columnIndex 索引
     * @return 字段值
     */
    T get(Row rs, int columnIndex);

    /**
     * 为缓冲语句设置值
     * <p>
     * 一个值可以被设置到多个占位符中
     * @param statement 缓冲语句
     * @param value     值
     * @param index     占位符位置，从 0 开始
     * @return 实际被设置到Statement中的值。<br>
     * 许多数据类型在设置到JDBC
     * Statement中时需要转换类型，例如java.util.Date需要转换为java.sql.Date。
     */
    Statement set(Statement statement, Object value, Class<?> targetClass, int index);

    /**
     * @param statement
     * @param value
     * @param targetClass
     * @param parameterName
     * @return
     */
    Statement set(Statement statement, Object value, Class<?> targetClass, String parameterName);


    /**
     * 最终返回的类型
     * @return
     */
    Class<T> getDefaultJavaType();

    /**
     * 设置返回的class,大部分的情况下不需要实现,只对枚举或需要自定义返回类型的情况使用
     * 和getDefaultJavaType() 方法成对出现
     * @param clz 设置java的数据类型
     */
    default void setDefaultJavaType(Class<T> clz) {
        throw new UnsupportedOperationException(" not support!");
    }

    /**
     * 设置返回的class,大部分的情况下不需要实现,只对范型返回类型的情况使用
     * @param columnMapping
     */
    default void setColumnMapping(ColumnMapping columnMapping) {

    }

    /**
     * java.sql.Types的值
     * @return
     */
    Type getSqlType();

    /**
     * 设置sqlType,大部分不实现!
     * @param sqlType
     */
    default void setSqlType(int sqlType) {

    }

    /**
     * 获取sql表达式
     * @param value
     * @param profile
     * @return
     */
    default String getSqlExpression(T value, DBDialect profile) {
        return null;
    }
}
